import type { Type } from '@nestjs/common'

import {
  Body,
  Controller,
  Delete,
  Get,
  Post,
  Put,
  Query,
} from '@nestjs/common'
import { ApiOperation, IntersectionType, PartialType } from '@nestjs/swagger'
import { upperFirst } from 'lodash'
import pluralize from 'pluralize'

import { ApiResult } from '~/common/decorators/api-result.decorator'
import { DeleteDto } from '~/common/dto/delete.dto'
import { PagerDto } from '~/common/dto/pager.dto'
import { CreatorPipe } from '~/common/pipes/creator.pipe'
import { UpdaterPipe } from '~/common/pipes/updater.pipe'

import { BaseService } from './base.service'

export function BaseCrudFactory<
  E extends new (...args: any[]) => any,
>({ entity, dto, permissions }: { entity: E, dto?: Type<any>, permissions?: Record<string, string> }): Type<any> {
  const prefix = entity.name.toLowerCase().replace(/entity$/, '')
  const pluralizeName = pluralize(prefix) as string

  dto = dto ?? class extends entity {}

  class SaveDto extends dto {
    static readonly name = upperFirst(`${pluralizeName}SaveDto`)
  }
  class QueryDto extends IntersectionType(PagerDto, PartialType(SaveDto)) {
    static readonly name = upperFirst(`${pluralizeName}QueryDto`)
  }

  permissions = permissions ?? {
    PAGE: `${prefix}:page`,
    LIST: `${prefix}:list`,
    QUERY: `${prefix}:query`,
    CREATE: `${prefix}:create`,
    UPDATE: `${prefix}:update`,
    DELETE: `${prefix}:delete`,
  } as const

  @Controller(pluralizeName)
  class BaseController {
    constructor(private service: BaseService<E>) { }

    @Get('page')
    @ApiOperation({ summary: `获取${upperFirst(pluralizeName)}分页列表` })
    @ApiResult({ type: [entity], isPage: true })
    async page(@Query() dto: QueryDto) {
      return await this.service.page(dto)
    }

    @Get('list')
    @ApiOperation({ summary: `获取${upperFirst(pluralizeName)}列表` })
    @ApiResult({ type: [entity] })
    async list(@Query() dto: QueryDto) {
      return await this.service.list(dto)
    }

    @Get('get')
    @ApiOperation({ summary: `查询${upperFirst(pluralizeName)}详情` })
    @ApiResult({ type: entity })
    async get(@Query('id') id: number) {
      return await this.service.findOne(id)
    }

    @Post('create')
    @ApiOperation({ summary: `创建${upperFirst(pluralizeName)}` })
    async create(@Body(CreatorPipe) dto: SaveDto) {
      return await this.service.create(dto)
    }

    @Put('update')
    @ApiOperation({ summary: `更新${upperFirst(pluralizeName)}` })
    async update(@Body(UpdaterPipe) dto: SaveDto) {
      return await this.service.update(dto.id, dto)
    }

    @Delete('delete')
    @ApiOperation({ summary: `删除${upperFirst(pluralizeName)}` })
    async delete(@Query() dto: DeleteDto) {
      // 解析ids参数，支持单个和多个删除
      const ids = dto.ids.split(',').map(id => Number.parseInt(id.trim())).filter(id => !Number.isNaN(id))

      if (ids.length === 0) {
        throw new Error('Invalid ids parameter')
      }

      // 批量删除
      for (const id of ids) {
        await this.service.delete(id)
      }
    }
  }

  return BaseController
}
